package day27.Thread;

/**
 * Java多线程高级特性测试类
 * 演示线程优先级、守护线程和线程状态等高级特性
 * 
 * 本类通过三个测试方法展示了Java线程的高级特性：
 * 1. 线程优先级：展示如何通过设置优先级影响线程调度
 * 2. 守护线程：演示守护线程与用户线程的区别
 * 3. 线程状态：展示线程生命周期中的各种状态转换
 */
public class AdvancedThreadTest {
    public static void main(String[] args) {
        System.out.println("=== Java多线程高级特性测试 ===\n");
        
        // 测试1: 线程优先级
        testThreadPriority();
        
        // 测试2: 守护线程
        testDaemonThread();
        
        // 测试3: 线程状态
        testThreadState();
    }
    
    /**
     * 测试线程优先级
     * 演示如何设置线程优先级以及优先级对线程调度的影响
     * 
     * 线程优先级说明：
     * - Java线程优先级范围是1-10，其中1是最低优先级，10是最高优先级
     * - Thread.MIN_PRIORITY = 1 (最低优先级)
     * - Thread.NORM_PRIORITY = 5 (默认优先级)
     * - Thread.MAX_PRIORITY = 10 (最高优先级)
     * 
     * 注意：线程优先级只是给操作系统的一个建议，不能保证高优先级线程一定先执行完
     * 高优先级获得cpu处理概率更高
     */
    public static void testThreadPriority() {
        System.out.println("1. 线程优先级测试:");
        
        // 创建低优先级和高优先级线程任务
        // PriorityTask是一个实现了Runnable接口的任务类，用于执行计算密集型操作
        Thread lowPriority = new Thread(new PriorityTask("低优先级线程"), "LowPriorityThread");
        Thread highPriority = new Thread(new PriorityTask("高优先级线程"), "HighPriorityThread");
        
        // 设置优先级：MIN_PRIORITY=1, MAX_PRIORITY=10
        // setPriority方法用于设置线程的优先级，必须在启动线程前调用
        lowPriority.setPriority(Thread.MIN_PRIORITY);
        highPriority.setPriority(Thread.MAX_PRIORITY);
        
        // 启动线程，使线程进入RUNNABLE状态
        lowPriority.start();
        highPriority.start();
        
        try {
            // join()方法使当前线程（main线程）等待指定线程执行完毕后再继续执行
            // 这里是为了确保两个测试线程都执行完毕后再进行下一步测试
            lowPriority.join();
            highPriority.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        
        System.out.println();
    }
    
    /**
     * 测试守护线程
     * 演示守护线程的特点：当所有用户线程结束时，守护线程会自动结束
     * 
     * 守护线程说明：
     * - 守护线程是为其他线程提供服务的线程，例如垃圾回收线程
     * - 当JVM中所有非守护线程都结束时，守护线程会自动终止
     * - 守护线程必须在启动前通过setDaemon(true)设置
     * - 守护线程通常用于执行后台任务
     */
    public static void testDaemonThread() {
        System.out.println("2. 守护线程测试:");
        
        // 创建守护线程和用户线程
        // DaemonTask是守护线程执行的任务，会循环打印信息
        // UserTask是用户线程执行的任务，会执行有限次数的操作
        Thread daemonThread = new Thread(new DaemonTask(), "DaemonThread");
        Thread userThread = new Thread(new UserTask(), "UserThread");
        
        // 设置为守护线程（必须在启动前设置）
        // setDaemon(true)将线程标记为守护线程
        // 如果不设置，默认为用户线程(false)
        daemonThread.setDaemon(true);
        
        // 启动守护线程和用户线程
        daemonThread.start();
        userThread.start();
        
        try {
            // 等待用户线程执行完毕
            // join()方法使main线程等待userThread执行完成
            // 当userThread结束后，由于没有其他用户线程，daemonThread会自动结束
            userThread.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        
        System.out.println("用户线程执行完毕，程序即将结束，守护线程也会随之结束\n");
    }
    
    /**
     * 测试线程状态
     * 演示线程的生命周期中不同状态的转换
     * 
     * 线程状态说明：
     * - NEW: 线程被创建但尚未启动
     * - RUNNABLE: 线程正在Java虚拟机中执行
     * - BLOCKED: 线程被阻塞等待监视器锁
     * - WAITING: 线程无限期等待其他线程执行特定操作
     * - TIMED_WAITING: 线程等待其他线程执行特定操作，但有时间限制
     * - TERMINATED: 线程执行完毕
     */
    public static void testThreadState() {
        System.out.println("3. 线程状态测试:");
        
        // 创建线程对象，此时线程处于NEW状态
        Thread stateThread = new Thread(new StateTask(), "StateThread");
        
        // NEW状态：线程被创建但尚未启动
        // getState()方法返回线程的当前状态
        System.out.println("线程创建后状态: " + stateThread.getState());
        
        // 启动线程，线程进入RUNNABLE状态
        //start方法来源于Runnable接口
        stateThread.start();
        // RUNNABLE状态：线程正在Java虚拟机中执行
        System.out.println("线程启动后状态: " + stateThread.getState());
        
        try {
            // 短暂休眠，让stateThread线程有机会进入运行状态或等待状态
            Thread.sleep(100);
            // RUNNABLE或TIMED_WAITING状态：线程正在运行或等待
            // 具体状态取决于StateTask.run()方法中Thread.sleep()的执行情况
            System.out.println("线程运行中状态: " + stateThread.getState());
            
            // 等待线程执行完毕，main线程会阻塞直到stateThread执行完成
            stateThread.join();
            // TERMINATED状态：线程执行完毕
            System.out.println("线程结束后状态: " + stateThread.getState());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        
        System.out.println("\n测试完成!");
    }
}

/**
 * 优先级测试任务类
 * 实现Runnable接口，用于测试不同优先级线程的执行效率
 * 
 * 该类通过执行计算密集型任务(Math.sqrt)来消耗CPU时间，
 * 从而可以观察不同优先级对线程执行时间的影响
 */
class PriorityTask implements Runnable {
    private String taskName;
    
    // 构造函数，初始化任务名称
    public PriorityTask(String taskName) {
        this.taskName = taskName;
    }
    
    @Override
    public void run() {
        // 记录开始时间，用于计算执行耗时
        long startTime = System.currentTimeMillis();
        
        // 执行一些计算密集型任务，计算平方根
        // 这是一个CPU密集型操作，可以体现线程优先级的影响
        for (int i = 0; i < 1000000; i++) {
            Math.sqrt(i);
        }
        
        // 记录结束时间并输出执行时间
        // 通过比较不同优先级线程的执行时间，可以观察优先级对调度的影响
        long endTime = System.currentTimeMillis();
        System.out.println(taskName + " 执行时间: " + (endTime - startTime) + "ms");
    }
}

/**
 * 守护线程任务类
 * 实现Runnable接口，用于演示守护线程的特性
 * 
 * 该任务会无限循环执行，模拟守护线程的持续服务特性
 * 只有当所有用户线程结束后，守护线程才会自动终止
 */
class DaemonTask implements Runnable {
    @Override
    public void run() {
        // 守护线程会一直运行，直到所有用户线程结束
        // 这是一个无限循环，模拟守护线程的持续服务
        while (true) {
            System.out.println("守护线程正在运行...");
            try {
                // 每隔500ms执行一次，避免输出过于频繁
                // Thread.sleep()会使当前线程进入TIMED_WAITING状态
                Thread.sleep(500);
            } catch (InterruptedException e) {
                // 当线程被中断时会抛出InterruptedException
                e.printStackTrace();
            }
        }
    }
}

/**
 * 用户线程任务类
 * 实现Runnable接口，用于演示用户线程的执行
 * 
 * 该任务会执行有限次数的操作，模拟用户线程的正常执行流程
 * 当所有用户线程执行完毕后，程序会正常退出
 */
class UserTask implements Runnable {
    @Override
    public void run() {
        // 用户线程执行3次任务，每次间隔1秒
        // 模拟用户线程执行具体的业务逻辑
        for (int i = 1; i <= 3; i++) {
            System.out.println("用户线程执行第 " + i + " 次任务");
            try {
                // 每次执行任务后休眠1秒
                // Thread.sleep()会使当前线程进入TIMED_WAITING状态
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                // 当线程被中断时会抛出InterruptedException
                e.printStackTrace();
            }
        }
        System.out.println("用户线程任务完成");
    }
}

/**
 * 线程状态测试任务类
 * 实现Runnable接口，用于演示线程状态的变化
 * 
 * 该任务通过Thread.sleep()方法使线程进入TIMED_WAITING状态，
 * 从而可以观察线程状态的变化过程
 */
class StateTask implements Runnable {
    @Override
    public void run() {
        System.out.println("StateTask开始执行");
        try {
            // 模拟任务执行，线程进入TIMED_WAITING状态
            // Thread.sleep()会使当前线程暂停执行指定时间
            // 在此期间线程不会消耗CPU资源
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            // 当线程在sleep期间被中断时会抛出此异常
            e.printStackTrace();
        }
        System.out.println("StateTask执行完毕");
    }
}